
//
//  ZYQAppDelegate.m
//  小庆聊天室
//
//  Created by 张毓庆 on 13-12-8.
//  Copyright (c) 2013年 张毓庆. All rights reserved.
//

#import "ZYQAppDelegate.h"
#import "ZYQLoginUser.h"
#import "NSString+Helper.h"

@interface ZYQAppDelegate() <XMPPStreamDelegate,XMPPRosterDelegate>
{
    successBlock _successBlock;  // 连接成功的块代码
    failedBlock _failedBlock;    // 连接失败的块代码
    
    // xmpp重新连接xmppstream
    XMPPReconnect *_xmppReconnect;
    // 电子名片的存储
    XMPPvCardCoreDataStorage *_xmppCoreDataStorage;
    
    
    XMPPCapabilities            *_xmppCapabilities;     // 实体扩展模块
    XMPPCapabilitiesCoreDataStorage *_xmppCapabilitiesCoreDataStorage; // 数据存储模块
}

// 设置xmppStream
- (void)setupStream;
// 销毁xmppStream
- (void)teardownStream;
// 通知服务器用户上线
- (void)goOnLine;
// 通知服务器用户下线
- (void)goOffline;
// 连接到服务器
- (void)connect;
// 断开与服务器的连接
- (void)disconnect;
@end


@implementation ZYQAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.
    // 实例化Windows
    self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    // 设置xmpp流
    [self setupStream];
    return YES;
}
							
- (void)applicationWillResignActive:(UIApplication *)application
{
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
    
    [self disconnect];
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    
    // 使用此方法可以实现自动登录的特性，如果用户名和密码等信息不存在才需要登录
    [self connect];
}

// 退出程序的时候
- (void)dealloc
{
    [self teardownStream];
}

#pragma mark - 根据用户的状态显示stoyborad
- (void)showStoryBoardWithLogonState:(BOOL)isUserLogon
{
    UIStoryboard *storyBoard = nil;
    
    if (isUserLogon)
    {
        storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    }
    else
    {
        storyBoard = [UIStoryboard storyboardWithName:@"login" bundle:nil];
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        
        [self.window setRootViewController:storyBoard.instantiateInitialViewController];
        
        if (!self.window.isKeyWindow) {
            [self.window makeKeyAndVisible];
        }
    });
    
}



#pragma mark - xmpp相关的方法
#pragma mark 设置xmpp流
- (void)setupStream
{
    NSAssert(_xmppStream == nil, @"XMPPStream被多次实例化");
    
    // 实例化xmppStream
    _xmppStream = [[XMPPStream alloc]init];
    
    // 让XMPP在真机运行时支持后台，在模拟器上是不支持后台服务运行的
#if !TARGET_IPHONE_SIMULATOR
    {
        // 允许XMPPStream在真机运行时，支持后台网络通讯！
        [_xmppStream setEnableBackgroundingOnSocket:YES];
    }
#endif
    
    // 扩展模块
    // 重新连接扩展模块
    _xmppReconnect = [[XMPPReconnect alloc]init];
    // 电子名片的模块
    _xmppCoreDataStorage = [XMPPvCardCoreDataStorage sharedInstance];
    _xmppvCardModule = [[XMPPvCardTempModule alloc]initWithvCardStorage:_xmppCoreDataStorage];
    _xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc]initWithvCardTempModule:_xmppvCardModule];
    
    // 2.5 实体扩展模块
    _xmppCapabilitiesCoreDataStorage = [[XMPPCapabilitiesCoreDataStorage alloc] init];
    _xmppCapabilities = [[XMPPCapabilities alloc] initWithCapabilitiesStorage:_xmppCapabilitiesCoreDataStorage];
    
    // 花名册模块
    _xmppRosterCoreDataStorage = [[XMPPRosterCoreDataStorage alloc]init];
    _xmppRoster = [[XMPPRoster alloc]initWithRosterStorage:_xmppRosterCoreDataStorage];
    
    // 聊天消息存储
    _xmppMessageArchivingCoreDataStorage = [[XMPPMessageArchivingCoreDataStorage alloc]init];
    _xmppMessageArchiving = [[XMPPMessageArchiving alloc]initWithMessageArchivingStorage:_xmppMessageArchivingCoreDataStorage];
    
    // 将扩展模块添加到xmmstream中
    [_xmppReconnect activate:_xmppStream];
    [_xmppvCardModule activate:_xmppStream];
    [_xmppvCardAvatarModule activate:_xmppStream];
    [_xmppRoster activate:_xmppStream];
    [_xmppCapabilities activate:_xmppStream];
    [_xmppMessageArchiving activate:_xmppStream];
    
    // 设置好友自动添加机制
    [_xmppRoster setAutoAcceptKnownPresenceSubscriptionRequests:YES];
    // 自动从服务器更新好友信息
    [_xmppRoster setAutoFetchRoster:YES];
    
    // 添加代理
    [_xmppStream addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
    [_xmppRoster addDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
}

#pragma mark 销毁xmppStream及其扩展模块
- (void)teardownStream
{
    // 删除代理
    [_xmppStream removeDelegate:self];
    [_xmppRoster removeDelegate:self];
    
    // 取消激活
    [_xmppReconnect deactivate];
    [_xmppvCardModule deactivate];
    [_xmppvCardAvatarModule deactivate];
    [_xmppRoster deactivate];
    [_xmppCapabilities deactivate];
    [_xmppMessageArchiving deactivate];
    
    // 断开连接
    [_xmppStream disconnect];
    
    // 内存清理
    _xmppStream = nil;
    _xmppReconnect = nil;
    _xmppvCardModule = nil;
    _xmppvCardModule = nil;
    _xmppvCardAvatarModule = nil;
    _xmppRoster = nil;
    _xmppRosterCoreDataStorage = nil;
    _xmppCapabilities = nil;
    _xmppCapabilitiesCoreDataStorage = nil;
    _xmppMessageArchiving = nil;
    _xmppMessageArchivingCoreDataStorage = nil;
}

#pragma mark 通知服务器用户上线
- (void)goOnLine
{
    // 实例化一个展现,展现的默认状态就是可用的
    XMPPPresence *presence = [XMPPPresence presence];
    
    // 将展现发送给服务器
    [_xmppStream sendElement:presence];
}

#pragma mark 通知服务器用户下线
- (void)goOffline
{
    // 实例化一个展现
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    
    // 将展现发送给服务器
    [_xmppStream sendElement:presence];
}


#pragma mark 连接到服务器
- (void)connect
{
    // 如果当前已经连接了服务器直接返回
    if ([_xmppStream isConnected])
    {
        return;
    }
    
    NSString *hostName = [ZYQLoginUser sharedZYQLoginUser].hostName;
    NSString *userName = [ZYQLoginUser sharedZYQLoginUser].myJIDName;
    
    
    // 如果没有主机名或用户名（通常第一次运行时会出现），直接显示登录窗口
    if ([hostName isEmptyString] || [userName isEmptyString])
    {
        // 直接显示登录窗口
        [self showStoryBoardWithLogonState:NO];
        
        return;
    }
    
    // 设置xmppstream的jid和主机
    [_xmppStream setMyJID:[XMPPJID jidWithString:userName]];
    [_xmppStream setHostName:hostName];
    
    
    // 开始连接
    NSError *error = nil;
    
    [_xmppStream connectWithTimeout:XMPPStreamTimeoutNone error:&error];
    
    if (error)
    {
        NSLog(@"连接请求发送出错 %@",error);
    }
    else
    {
        NSLog(@"连接请求发送成功");
    }
}

- (void)connectWithSuccessBlock:(successBlock)success failed:(failedBlock)failed
{
    // 记录一下块代码
    _successBlock = success;
    _failedBlock = failed;
    
    // 如果已经存在连接了就先断开连接，然后在连接
    if ([_xmppStream isConnected])
    {
        [_xmppStream disconnect];
    }
    
    [self connect];
}

#pragma mark 断开服务器的连接
- (void)disconnect
{
    // 通知服务器下线
    [self goOffline];
    
    [_xmppStream disconnect];
}

- (void)logout
{
    [self disconnect];
    
    //显示用户登录的界面
    [self showStoryBoardWithLogonState:NO];
    
}

#pragma mark - 代理方法

#pragma mark 连接完成成功
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
    NSString *password = [ZYQLoginUser sharedZYQLoginUser].password;
    
    if (_isRegisterUser)
    {
        // 用户注册的，发送注册请求
        [_xmppStream registerWithPassword:password error:nil];
    }
    else
    {
        // 用户登录
        [_xmppStream authenticateWithPassword:password error:nil];
    }
}


#pragma mark 注册成功
- (void)xmppStreamDidRegister:(XMPPStream *)sender
{
    _isRegisterUser = NO;
    
    [_xmppStream authenticateWithPassword:[ZYQLoginUser sharedZYQLoginUser].password error:nil];
}

#pragma mark 注册失败 (用户名已经存在了)
- (void)xmppStream:(XMPPStream *)sender didNotRegister:(DDXMLElement *)error
{
    _isRegisterUser = NO;
    
    if (_failedBlock != nil)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            _failedBlock();
        });
    }
}

#pragma mark 身份验证通过
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
    if (_successBlock != nil)
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            _successBlock();
        });
    }
    
    // 通知服务器用户上线
    [self goOnLine];
    
    // 显示主storyboard
    [self showStoryBoardWithLogonState:YES];
}


#pragma mark 密码错误，身份验证失败
- (void)xmppStream:(XMPPStream *)sender didNotAuthenticate:(DDXMLElement *)error
{
    if (_failedBlock != nil)
    {        dispatch_async(dispatch_get_main_queue(), ^{
            _failedBlock();
        });
    }

    
    // 显示登录storyboard
    [self showStoryBoardWithLogonState:NO];
}

#pragma mark - 接受到一个用户展现
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
//    NSLog(@"接受到用户展现- %@",presence);
    if ([presence.type isEqualToString:@"subscribe"])
    {
        XMPPJID *from = [presence from];
        
        // 接受来自好友的用户订阅
        [_xmppRoster acceptPresenceSubscriptionRequestFrom:from andAddToRoster:YES];
    }
}



#pragma mark 接收消息
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
    NSLog(@"接收到用户消息 - %@", message);
}

#pragma mark - XMPPRoster代理
- (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence
{
    NSLog(@"接收到其他用户的请求 %@", presence);
}

@end

